﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using _01_Tower4._0.GameFrame.System;
using _01_Tower4._0.Tool;
using _01_Tower4._0.CharacterBase;
using _01_Tower4._0.GameFrame.System;
using _01_Tower4._0.Tool;
using _01_Tower4._0.Interface;
using _01_Tower4._0.Scene;
using System.Numerics;
using _01_Tower4._0.CharacterBase.EnemyType;

namespace _01_Tower4._0
{
    struct Pos
    {
        public int x;
        public int y;
        public static bool operator ==(Pos left, Pos right)
        {
            return left.x == right.x && left.y == right.y;
        }
        public static bool operator !=(Pos left, Pos right)
        {
            return left.x != right.x || left.y == right.y;
        }
    }

    internal class Map
    {
        public enum Type
        {
            BrushMagenta = -10,
            BrushDarkYellow = -11,
            BrushGray = -12,
            BrushBlack = -13,
            BrushBlue = -14,
            BrushRed = -15,
            BrushWhite = -16,
            BrushGreen = -17,
            BrushDarkGreen = -18,
            BrushCyan = -19,
            BrushDarkBlue = -20,
            BrushDarkCyan = -21,
            BrushDarkRed = -22,
            BrushDarkGray = -23,
            BrushDarkMagenta = -24,
            BrushYellow = -25,
            TrapWall = -1,
            None = 1,
            Wall = 0,
            Mon = 2,
            Tool = 3,
            Map1Step0 = 4,
            Hero = 6,
            MonSlime = 7,
            RKing = 12,
            FKing = 13,
            Map1Key0 = 14,
            Map2Step0 = 15,
            Map2Button0 = 16,
            Map2Key0 = 17,
            Map2Key1 = 18,
            Map2Step1 = 19,
            MonGoblin = 20,
            NpcItemShop = 21,
            NpcSkillShop = 22,
            Npc1 = 23,
            Npc2 = 24,
            NpcPastor = 25,
            NpcSoldier2 = 26,
            Map3Step0 = 27,
            SkillArcane = 30,
            SkillHealing = 31,
            GoblinFall = 32,
            SlimeFall = 33,
            BluePotion = 34,
            MaO = 35,
        };
        public struct Data
        {
            public Pos pos;
            public Type type;
        }

        public Data[,] data;
        public int currentIndex;
        public int offsetX, offsetY;
        public int width, height;
        string[] paths;
        IScene scene;
        public static int pasterDialogId;
        public static int rKingDialogId;
        public static int npc1DialogId;
        public static int npc2DialogId;

        public Map(string[] paths, int width, int height,int offsetX, int offsetY, IScene scene)
        {
            data = new Data[paths.Length, width * height];
            this.offsetX = offsetX;
            this.offsetY = offsetY;
            this.width = width;
            this.height = height;
            this.paths = paths;
            this.scene = scene;
            LoadData();
            currentIndex = -1;
            pasterDialogId = 240;
            rKingDialogId = 10;
            npc1DialogId = 200;
            npc2DialogId = 220;
        }

        public void LoadData()
        {
            for (int i = 0; i < paths.Length; i++)
            {
                string temp = DataSystem.Instance.LoadData(paths[i]);

                string[] lines = temp.Split('\n');
                for (int j = 0; j < height; j++)
                {
                    string[] elements = lines[j].Split(',');
                    for (int k = 0; k < width; k++)
                    {
                        //序号 = 行号 * 列数 + 列号
                        int index = j * width + k;
                        data[i, index].pos.x = k;
                        data[i, index].pos.y = j;
                        data[i, index].type = (Type)int.Parse(elements[k]);
                    }
                }
            }
        }
        
        public void Init()
        {
            //LoadData();
            for (int i = 0; i < data.GetLength(1); i++)
            {
                switch (data[currentIndex, i].type)
                {
                    case Type.Hero:
                        ((SceneMap1)scene).hero.SetPos(data[currentIndex, i].pos);
                        break;
                    case Type.FKing:
                        ((SceneMap1)scene).fKing.Add(new Npc(data[currentIndex, i].pos, "M", i, 0,ConsoleColor.Yellow));
                        break;
                    case Type.MaO:
                        ((SceneMap1)scene).maO.Add(new Npc(data[currentIndex, i].pos, "W", i, 100, ConsoleColor.Red));
                        break;
                    case Type.RKing:
                        ((SceneMap1)scene).rKing.Add(new Npc(data[currentIndex, i].pos, "M", i, rKingDialogId, ConsoleColor.Yellow));
                        break;
                    case Type.NpcPastor:
                        ((SceneMap1)scene).pastor.Add(new Npc(data[currentIndex, i].pos, "Y", i, pasterDialogId, ConsoleColor.Yellow));
                        break;
                    //case Type.NpcSoldier2:
                    //    ((SceneMap1)scene).fKing.Add(new Npc(data[currentIndex, i].pos, "Y", i, 0, ConsoleColor.Yellow));
                    //    break;
                    //case Type.NpcItemShop:
                    //    ((SceneMap1)scene).fKing.Add(new Npc(data[currentIndex, i].pos, "I", i, 0, ConsoleColor.Yellow));
                    //    break;
                    //case Type.NpcSkillShop:
                    //    ((SceneMap1)scene).fKing.Add(new Npc(data[currentIndex, i].pos, "S", i, 0, ConsoleColor.Yellow));
                    //    break;
                    case Type.Npc1:
                        ((SceneMap1)scene).npc1.Add(new Npc(data[currentIndex, i].pos, "A", i, npc1DialogId, ConsoleColor.Blue));
                        break;
                    case Type.Npc2:
                        ((SceneMap1)scene).npc2.Add(new Npc(data[currentIndex, i].pos, "A", i, npc2DialogId, ConsoleColor.Green));
                        break;
                    #region 史莱姆
                    case Type.MonSlime:
                        ((SceneMap1)scene).slime.Add(new EnemySlime("史莱姆", 100, 100, 50, 50, 26, 15, data[currentIndex, i].pos, this, "O",ConsoleColor.Blue, (SceneMap1)scene));
                        break;
                    #endregion
                    #region 哥布林
                    case Type.MonGoblin:
                        ((SceneMap1)scene).goblin.Add(new EnemyGoblin("哥布林", 100, 100,50, 50, 26, 15, data[currentIndex, i].pos, this, "X", ConsoleColor.Green, (SceneMap1)scene));
                        break;
                        #endregion
                }
            }
        }

        public void Render()
        {
            for (int i = 0; i < data.GetLength(1); i++)
            {
                switch (data[currentIndex, i].type)
                {
                    case Type.None:
                        break;
                    case Type.Wall:
                        Utility.MyPrint("X", data[currentIndex, i].pos.x, data[currentIndex, i].pos.y, ConsoleColor.Gray, ConsoleColor.Gray);
                        break;
                    case Type.TrapWall:
                        Utility.MyPrint("I", data[currentIndex, i].pos.x, data[currentIndex, i].pos.y, ConsoleColor.Yellow, ConsoleColor.Red);
                        break;
                    case Type.Tool:
                        Utility.MyPrint("+", data[currentIndex, i].pos.x, data[currentIndex, i].pos.y, ConsoleColor.Red);
                        break;
                    case Type.BluePotion:
                        Utility.MyPrint("u", data[currentIndex, i].pos.x, data[currentIndex, i].pos.y, ConsoleColor.Blue);
                        break;
                    case Type.Map2Button0:
                        Utility.MyPrint(".", data[currentIndex, i].pos.x, data[currentIndex, i].pos.y, ConsoleColor.DarkBlue);
                        break;
                    case Type.GoblinFall:
                        Utility.MyPrint("x", data[currentIndex, i].pos.x, data[currentIndex, i].pos.y, ConsoleColor.Green);
                        break;
                    case Type.SlimeFall:
                        Utility.MyPrint("o", data[currentIndex, i].pos.x, data[currentIndex, i].pos.y, ConsoleColor.Blue);
                        break;

                    case Type.SkillArcane:
                        Utility.MyPrint("*", data[currentIndex, i].pos.x, data[currentIndex, i].pos.y, ConsoleColor.Magenta);
                        break;
                    case Type.SkillHealing:
                        Utility.MyPrint("*", data[currentIndex, i].pos.x, data[currentIndex, i].pos.y, ConsoleColor.Green);
                        break;

                    #region Step
                    case Type.Map1Step0:
                        Utility.MyPrint("L", data[currentIndex, i].pos.x, data[currentIndex, i].pos.y, ConsoleColor.White);
                        break;
                    case Type.Map2Step0:
                        Utility.MyPrint("L", data[currentIndex, i].pos.x, data[currentIndex, i].pos.y, ConsoleColor.White);
                        break;
                    case Type.Map2Step1:
                        Utility.MyPrint("L", data[currentIndex, i].pos.x, data[currentIndex, i].pos.y, ConsoleColor.Blue);
                        break;
                    case Type.Map3Step0:
                        Utility.MyPrint("L", data[currentIndex, i].pos.x, data[currentIndex, i].pos.y, ConsoleColor.Yellow);
                        break;
                    #endregion

                    #region Key
                    case Type.Map1Key0:
                        Utility.MyPrint("Ī", data[currentIndex, i].pos.x, data[currentIndex, i].pos.y, ConsoleColor.Yellow);
                        break;
                    case Type.Map2Key0:
                        Utility.MyPrint("Ī", data[currentIndex, i].pos.x, data[currentIndex, i].pos.y, ConsoleColor.Yellow);
                        break;
                    case Type.Map2Key1:
                        Utility.MyPrint("Ī", data[currentIndex, i].pos.x, data[currentIndex, i].pos.y, ConsoleColor.Yellow);
                        break;
                    #endregion

                    #region Brush
                    case Type.BrushMagenta:
                        Utility.MyPrint("Ī", data[currentIndex, i].pos.x, data[currentIndex, i].pos.y, ConsoleColor.Magenta);
                        break;
                    case Type.BrushDarkYellow:
                        Utility.MyPrint("Ī", data[currentIndex, i].pos.x, data[currentIndex, i].pos.y, ConsoleColor.DarkYellow);
                        break;
                    case Type.BrushGray:
                        Utility.MyPrint("Ī", data[currentIndex, i].pos.x, data[currentIndex, i].pos.y, ConsoleColor.Gray);
                        break;
                    case Type.BrushBlack:
                        Utility.MyPrint("Ī", data[currentIndex, i].pos.x, data[currentIndex, i].pos.y, ConsoleColor.Black);
                        break;
                    case Type.BrushBlue:
                        Utility.MyPrint("Ī", data[currentIndex, i].pos.x, data[currentIndex, i].pos.y, ConsoleColor.Blue);
                        break;
                    case Type.BrushRed:
                        Utility.MyPrint("Ī", data[currentIndex, i].pos.x, data[currentIndex, i].pos.y, ConsoleColor.Red);
                        break;
                    case Type.BrushWhite:
                        Utility.MyPrint("Ī", data[currentIndex, i].pos.x, data[currentIndex, i].pos.y, ConsoleColor.White);
                        break;
                    case Type.BrushGreen:
                        Utility.MyPrint("Ī", data[currentIndex, i].pos.x, data[currentIndex, i].pos.y, ConsoleColor.Green);
                        break;
                    case Type.BrushDarkGreen:
                        Utility.MyPrint("Ī", data[currentIndex, i].pos.x, data[currentIndex, i].pos.y, ConsoleColor.DarkGreen);
                        break;
                    case Type.BrushCyan:
                        Utility.MyPrint("Ī", data[currentIndex, i].pos.x, data[currentIndex, i].pos.y, ConsoleColor.Cyan);
                        break;
                    case Type.BrushDarkBlue:
                        Utility.MyPrint("Ī", data[currentIndex, i].pos.x, data[currentIndex, i].pos.y, ConsoleColor.DarkBlue);
                        break;
                    case Type.BrushDarkCyan:
                        Utility.MyPrint("Ī", data[currentIndex, i].pos.x, data[currentIndex, i].pos.y, ConsoleColor.DarkCyan);
                        break;
                    case Type.BrushDarkRed:
                        Utility.MyPrint("Ī", data[currentIndex, i].pos.x, data[currentIndex, i].pos.y, ConsoleColor.DarkRed);
                        break;
                    case Type.BrushDarkGray:
                        Utility.MyPrint("Ī", data[currentIndex, i].pos.x, data[currentIndex, i].pos.y, ConsoleColor.DarkGray);
                        break;
                    case Type.BrushDarkMagenta:
                        Utility.MyPrint("Ī", data[currentIndex, i].pos.x, data[currentIndex, i].pos.y, ConsoleColor.DarkMagenta);
                        break;
                    case Type.BrushYellow:
                        Utility.MyPrint("Ī", data[currentIndex, i].pos.x, data[currentIndex, i].pos.y, ConsoleColor.Yellow);
                        break;
                        #endregion
                }
            }
        }

        public void ChangeMap(int index)
        {
            if (index < 0 || index >= data.GetLength(0) || index == currentIndex)
            {
                return;
            }
            End();
            currentIndex = index;
            Init();
            Console.Clear();
        }
        public void ChangePicture(int index)
        {
            if (index < 0 || index >= data.GetLength(0))
            {
                Console.WriteLine("地图不存在！");
                return;
            }
            currentIndex = index;
            //Console.Clear();
            for (int i = 0; i < 60; i++)
            {
                for (int j = 0; j < 30; j++)
                {
                    Utility.MyPrint(" ", i, j);
                }
            }
        }

        public Type GetType(Pos pos)
        {
            int index = pos.y * width + pos.x;
            return data[currentIndex, index].type;
        }

        public void SetType(Pos pos, Type type)
        {
            int index = pos.y * width + pos.x;
            data[currentIndex, index].type = type;
        }

        void End()
        {
            ((SceneMap1)scene).slime.Clear();
            ((SceneMap1)scene).goblin.Clear();
            ((SceneMap1)scene).rKing.Clear();
            ((SceneMap1)scene).maO.Clear();
            ((SceneMap1)scene).pastor.Clear();
            ((SceneMap1)scene).npc1.Clear();
            ((SceneMap1)scene).npc2.Clear();
        }
    }
}
